home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 85 / CD Temático 40 Febrero 2004.iso / DOS / testdisk / src / intrface.c < prev    next >
Encoding:
C/C++ Source or Header  |  2004-01-09  |  42.7 KB  |  1,737 lines

  1. /*
  2.  
  3.     File: intrface.c
  4.  
  5.     Copyright (C) 1998-2004 Christophe GRENIER <grenier@cgsecurity.org>
  6.   
  7.     This software is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation; either version 2 of the License, or
  10.     (at your option) any later version.
  11.   
  12.     This program is distributed in the hope that it will be useful,
  13.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.     GNU General Public License for more details.
  16.   
  17.     You should have received a copy of the GNU General Public License
  18.     along with this program; if not, write to the Free Software
  19.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21.  */
  22. #include <stdarg.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <ctype.h>
  27. #include <unistd.h>    /* geteuid */
  28. #include "types.h"
  29. #include "common.h"
  30. #include "lang.h"
  31. #include "intrface.h"
  32. #include "readpart.h"
  33. #include "godmode.h"
  34. #include "fnctdsk.h"
  35. #include "testdisk.h"
  36. #include "fat.h"
  37. #include "ext2_dir.h"
  38. #include "rfs.h"
  39. #include "ntfs.h"
  40. #include "adv.h"
  41.  
  42. extern char* nom_os[256];
  43. static void interface_options(int *paranoid,int *dump_ind,int *fast_mode,int *align,int *recover_cih,int *allow_partial_last_cylinder,int *ask_part_order,int *halt_on_errors, int *max_ext);
  44. #define GS_DEFAULT -1
  45. #define GS_key_ESCAPE -2
  46. static void aff_CHS_from_LBA(WINDOW *window, const t_param_disk *disk_car, dword hd_offset);
  47. static void aff_CHS_from_LBA_buffer(const t_param_disk *disk_car, dword hd_offset);
  48. static void aff_CHS_from_LBA_rapport(const t_param_disk *disk_car, dword hd_offset);
  49.  
  50.  
  51. int get_string(char *str, int len, char *def)
  52. {
  53.     int c;
  54.     int i = 0;
  55.     int x, y;
  56.     int use_def = FALSE;
  57.  
  58.     getyx(stdscr, y, x);
  59.     wclrtoeol(stdscr);
  60.  
  61.     str[0] = 0;
  62.  
  63.     if (def != NULL) {
  64.     mvwaddstr(stdscr,y, x, def);
  65.     wmove(stdscr,y, x);
  66.     use_def = TRUE;
  67.     }
  68.  
  69.     wrefresh(stdscr);
  70.     while ((c = wgetch(stdscr)) != '\n' && c != key_CR) {
  71.     switch (c) {
  72.     case key_ESC:
  73.         wmove(stdscr,y, x);
  74.         wclrtoeol(stdscr);
  75.         wrefresh(stdscr);
  76.         return GS_key_ESCAPE;
  77.     case KEY_DC:
  78.     case KEY_BACKSPACE:
  79.         if (i > 0) {
  80.         str[--i] = 0;
  81.         mvaddch(y, x+i, ' ');
  82.         wmove(stdscr,y, x+i);
  83.         } else if (use_def) {
  84.         wclrtoeol(stdscr);
  85.         use_def = FALSE;
  86.         }
  87.         break;
  88.     default:
  89.         if (i < len && isprint(c)) {
  90.         mvaddch(y, x+i, c);
  91.         if (use_def) {
  92.             wclrtoeol(stdscr);
  93.             use_def = FALSE;
  94.         }
  95.         str[i++] = c;
  96.         str[i] = 0;
  97.         }
  98.     }
  99.     wrefresh(stdscr);
  100.     }
  101.  
  102.     if (use_def)
  103.     return GS_DEFAULT;
  104.     else
  105.     return i;
  106. }
  107.  
  108. int wgetch_nodelay(WINDOW *window)
  109. {
  110.   int res;
  111.   nodelay(window,TRUE);
  112.   res=wgetch(window);
  113.   nodelay(window,FALSE);
  114.   return res;
  115. }
  116.  
  117. /*
  118.  * Actual function which prints the button bar and highlights the active button
  119.  * Should not be called directly. Call function menuSelect instead.
  120.  */
  121.  
  122. int wmenuUpdate(WINDOW *window, int y, int x, const struct MenuItem *menuItems, const unsigned int itemLength, const char *available, const int menuType, unsigned int current)
  123. {
  124.     unsigned int i, lmargin = x, ymargin = y;
  125.     const char *mcd;
  126.  
  127.     /* Print available buttons */
  128.     for( i = 0; menuItems[i].key!=0; i++ )
  129.     {
  130.       char buff[80];
  131.       unsigned int lenName;
  132.       const char *mi;
  133.       wmove(window, y, x ); wclrtoeol(window);
  134.  
  135.     /* Search next available button */
  136.     while( menuItems[i].key!=0 && strchr(available, menuItems[i].key)==NULL )
  137.     {
  138.         i++;
  139.     }
  140.     if( menuItems[i].key==0 ) break; /* No more menu items */
  141.  
  142.     /* If selected item is not available and we have bypassed it,
  143.        make current item selected */
  144.     if( current < i && menuItems[current].key < 0 ) current = i;
  145.  
  146.     /* If current item is selected, highlight it */
  147.     if( current == i )
  148.     {
  149.       /*attron( A_REVERSE )*/
  150.       wstandout (window);
  151.     }
  152.  
  153.     /* Print item */
  154.     mi = menuItems[i].name;
  155.     lenName = strlen( mi );
  156.     if(lenName>=sizeof(buff))
  157.     {
  158.       ecrit_rapport("\nBUG: %s\n",mi);
  159.     }
  160.     if(lenName > itemLength)
  161.     {
  162.       if( menuType & MENU_BUTTON )
  163.         snprintf(buff, sizeof(buff),"[%s]",mi);
  164.       else
  165.         snprintf(buff, sizeof(buff),"%s",mi);
  166.     }
  167.     else
  168.     {
  169.       if( menuType & MENU_BUTTON )
  170.         snprintf( buff, sizeof(buff),"[%*s%-*s]", (itemLength - lenName) / 2, "",
  171.             (itemLength - lenName + 1) / 2 + lenName, mi );
  172.       else
  173.         snprintf( buff, sizeof(buff),"%*s%-*s", (itemLength - lenName) / 2, "",
  174.             (itemLength - lenName + 1) / 2 + lenName, mi );
  175.     }
  176.     mvwaddstr(window, y, x, buff );
  177.  
  178.     /* Lowlight after selected item */
  179.     if( current == i )
  180.     {
  181.       /*attroff( A_REVERSE )*/
  182.       wstandend (window);
  183.     }
  184.     /* Calculate position for the next item */
  185.     if( menuType & MENU_VERT )
  186.     {
  187.         y += 1;
  188.         if( y >= WARNING_START )
  189.         {
  190.         y = ymargin;
  191.         x += itemLength + MENU_SPACING;
  192.         if( menuType & MENU_BUTTON ) x += 2;
  193.         }
  194.     }
  195.     else
  196.     {
  197.         x += itemLength + MENU_SPACING;
  198.         if( menuType & MENU_BUTTON ) x += 2;
  199.         if( x > COLUMNS - lmargin - 12 )
  200.         {
  201.         x = lmargin;
  202.         y ++ ;
  203.         }
  204.     }
  205.     }
  206.     /* Print the description of selected item */
  207.     mcd = menuItems[current].desc;
  208.     mvwaddstr(window, WARNING_START + 1, (COLUMNS - strlen( mcd )) / 2, mcd );
  209.     return y;
  210. }
  211.  
  212. /* This function takes a list of menu items, lets the user choose one *
  213.  * and returns the value keyboard shortcut of the selected menu item  */
  214.  
  215. int wmenuSelect(WINDOW *window, int y, int x, struct MenuItem *menuItems, const unsigned int itemLength, const char *available, int menuType, unsigned int menuDefault)
  216. {
  217.     int i, ylast = y, key = 0;
  218.     unsigned int current = menuDefault;
  219.     if( ( menuType & ( MENU_HORIZ | MENU_VERT ) )==0 )    
  220.     {
  221.     wdoprintf(window,"Menu without direction. Defaulting horizontal.");
  222.     menuType |= MENU_HORIZ;
  223.     }
  224.     /* Make sure that the current is one of the available items */
  225.     while(strchr(available, menuItems[current].key)==NULL)
  226.     {
  227.     current ++ ;
  228.     if( menuItems[current].key==0 )
  229.     {
  230.       current = 0;
  231.     }
  232.     }
  233.     /* Repeat until allowable choice has been made */
  234.     while( key==0 )
  235.     {
  236.     /* Display the menu */
  237.     ylast = wmenuUpdate( window, y, x, menuItems, itemLength, available,
  238.                 menuType, current );
  239.     wrefresh(window);
  240.     /* Don't put wgetch after the following wclrtoeol */
  241.     key = wgetch(window);
  242.  
  243.     /* Clear out all prompts and such */
  244.     for( i = y; i < ylast; i ++ )
  245.     {
  246.         wmove(window, i, x );
  247.         wclrtoeol(window);
  248.     }
  249.     wmove(window, WARNING_START + 1, 0 );
  250.     wclrtoeol(window);
  251.     /* Cursor keys */
  252.     switch(key)
  253.     {
  254.       case KEY_UP:
  255.         if( menuType & MENU_VERT )
  256.         {
  257.           do {
  258.         if( current-- == 0 )
  259.         {
  260.           while( menuItems[current+1].key ) current ++ ;
  261.         }
  262.           } while( strchr( available, menuItems[current].key )==NULL );
  263.           key = 0;
  264.         }
  265.         else
  266.           key = MENU_UP;
  267.         break;
  268.       case KEY_DOWN:
  269.         if( (menuType & MENU_VERT)!=0 )
  270.         {
  271.           do {
  272.         current ++ ;
  273.         if( menuItems[current].key==0 ) current = 0 ;
  274.           } while( strchr( available, menuItems[current].key )==NULL );
  275.           key = 0;
  276.         }
  277.         else
  278.           key = MENU_DOWN;
  279.         break;
  280.       case KEY_RIGHT:
  281.         if( menuType & MENU_HORIZ )
  282.         {
  283.           do {
  284.         current ++ ;
  285.         if( menuItems[current].key==0 ) 
  286.         {
  287.           current = 0 ;
  288.         }
  289.           } while( strchr( available, menuItems[current].key )==NULL );
  290.           key = 0;
  291.         }
  292.         else
  293.           key = MENU_RIGHT;
  294.         break;
  295.       case KEY_LEFT:
  296.         if( menuType & MENU_HORIZ )
  297.         {
  298.           do {
  299.         if( current-- == 0 )
  300.         {
  301.           while( menuItems[current + 1].key ) current ++ ;
  302.         }
  303.           } while( strchr( available, menuItems[current].key )==NULL );
  304.           key = 0;
  305.         }
  306.         else
  307.           key = MENU_LEFT;
  308.         break;
  309.     }
  310.     /* Enter equals to the keyboard shortcut of current menu item */
  311.     if((key==13) || (key==10) || (key==KEY_ENTER) ||(((menuType & MENU_HORIZ) == 0) && (key==MENU_RIGHT || key==MENU_LEFT)))
  312.         key = menuItems[current].key;
  313. #ifdef PADENTER
  314.     if(key==PADENTER)
  315.       key = menuItems[current].key;
  316. #endif
  317.  
  318.     /* Should all keys to be accepted? */
  319.     if( key && (menuType & MENU_ACCEPT_OTHERS) ) break;
  320.     /* Is pressed key among acceptable ones */
  321.     if( key!=0 && (strchr(available, toupper(key))!=NULL || strchr(available, key)!=NULL))
  322.         break;
  323.     /* The key has not been accepted so far -> let's reject it */
  324. #ifdef DEBUG
  325.     if( key )
  326.     {
  327.         wmove(window,5,0);
  328.         wdoprintf(window,"key %03X",key);
  329.         putchar( BELL );
  330.     }
  331. #endif
  332.     key = 0;
  333.     }
  334.     /* Clear out prompts and such */
  335.     for( i = y; i <= ylast; i ++ )
  336.     {
  337.     wmove(window, i, x );
  338.     wclrtoeol(window);
  339.     }
  340.     wmove(window, WARNING_START + 1, 0 );
  341.     wclrtoeol(window);
  342.     return key;
  343. }
  344.  
  345. /* Function menuSelect takes way too many parameters  *
  346.  * Luckily, most of time we can do with this function */
  347.  
  348. int wmenuSimple(WINDOW *window,struct MenuItem *menuItems, int menuDefault)
  349. {
  350.     unsigned int i, j, itemLength = 0;
  351.     char available[MENU_MAX_ITEMS];
  352.  
  353.     for(i = 0; menuItems[i].key; i++)
  354.     {
  355.     j = strlen(menuItems[i].name);
  356.     if( j > itemLength ) itemLength = j;
  357.     available[i] = menuItems[i].key;
  358.     }
  359.     available[i] = 0;
  360.     return wmenuSelect(window,18, 0, menuItems, itemLength, available, MENU_HORIZ | MENU_BUTTON, menuDefault);
  361. }
  362.  
  363. /* End of command menu support code */
  364.  
  365. unsigned int ask_number(const unsigned int val_cur, const unsigned int val_min, const unsigned int val_max, const char * _format, ...)
  366. {
  367.   char res[200];
  368.   char res2[200];
  369.   char response[LINE_LENGTH];
  370.   char def[LINE_LENGTH];
  371.   unsigned int tmp_val;
  372.   va_list ap;
  373.   va_start(ap,_format);
  374.   vsnprintf(res,sizeof(res),_format,ap);
  375.   snprintf(res2,sizeof(res2),"(%u-%u) :",val_min,val_max);
  376.   va_end(ap);
  377.  
  378.   mvwaddstr(stdscr,COMMAND_LINE_Y, COMMAND_LINE_X, res);
  379.   waddstr(stdscr,res2);
  380.   sprintf(def, "%u", val_cur);
  381.   if (get_string(response, LINE_LENGTH, def) > 0)
  382.   {
  383.     tmp_val = atoi(response);
  384.     if (tmp_val >= val_min && tmp_val <= val_max)
  385.       return tmp_val;
  386.   }
  387.   return val_cur;
  388. }
  389.  
  390. void aff_copy_full(WINDOW *window)
  391. {
  392.   wclear(window);
  393.   keypad(window, TRUE); /* Need it to get arrow key */
  394.   mvwaddstr(window,0,0,msg_Copyright);
  395. #ifdef DJGPP
  396.   wdoprintf(window,"Dos version\n\n");
  397. #elif defined(BSD)
  398.   wdoprintf(window,"BSD version\n\n");
  399. #elif defined(LINUX)
  400.   wdoprintf(window,"Linux version\n\n");
  401. #else
  402.   wdoprintf(window,"Undefined OS\n\n");
  403. #endif
  404. }
  405.  
  406. void aff_copy(WINDOW *window)
  407. {
  408.   wclear(window);
  409.   keypad(window, TRUE); /* Need it to get arrow key */
  410.   mvwaddstr(window,0,0,msg_Copyright);
  411. }
  412.  
  413.  
  414. void dump(WINDOW *window, const void *nom_dump,unsigned int lng)
  415. {
  416.   unsigned int i,j;
  417.   unsigned int pos=0;
  418.   unsigned char car;
  419.   int done=0;
  420.   int menu=2;   /* default : quit */
  421.   unsigned int nbr_line;
  422.   struct MenuItem menuDump[]=
  423.   {
  424.     { 'P', "Previous",""},
  425.     { 'N', "Next","" },
  426.     { 'Q',"Quit","Quit dump section"},
  427.     { 0, NULL, NULL }
  428.   };
  429.   nbr_line=lng/0x10;
  430.   if(lng%0x10!=0)
  431.     nbr_line++;
  432.   /* write dump to log file*/
  433.   for (i=0; (i<nbr_line); i++)
  434.   {
  435.     ecrit_rapport("%04X ",i*0x10);
  436.     for(j=0; j< 0x10;j++)
  437.     {
  438.       if(i*0x10+j<lng)
  439.       {
  440.     car=*((const unsigned char *)nom_dump+i*0x10+j);
  441.     ecrit_rapport("%02x", car);
  442.       }
  443.       else
  444.     ecrit_rapport("  ");
  445.       if(j%4==(4-1))
  446.     ecrit_rapport(" ");
  447.     }
  448.     ecrit_rapport("  ");
  449.     for(j=0; j< 0x10;j++)
  450.     {
  451.       if(i*0x10+j<lng)
  452.       {
  453.     car=*((const unsigned char*)nom_dump+i*0x10+j);
  454.     if ((car<32)||(car >= 127))
  455.       ecrit_rapport(".");
  456.     else
  457.       ecrit_rapport("%c",  car);
  458.       }
  459.       else
  460.     ecrit_rapport("  ");
  461.     }
  462.     ecrit_rapport("\n");
  463.   }
  464.   /* ncurses interface */
  465.   mvwaddstr(window,DUMP_Y,DUMP_X,msg_DUMP_HEXA);
  466.   /* On pourrait utiliser wscrl */
  467.   do
  468.   {
  469.     for (i=pos; (i<nbr_line)&&((i-pos)<DUMP_MAX_LINES); i++)
  470.     {
  471.       wmove(window,DUMP_Y+i-pos,DUMP_X);
  472.       wclrtoeol(window);
  473.       wdoprintf(window,"%04X ",i*0x10);
  474.       for(j=0; j< 0x10;j++)
  475.       {
  476.     if(i*0x10+j<lng)
  477.     {
  478.       car=*((const unsigned char*)nom_dump+i*0x10+j);
  479.       wdoprintf(window,"%02x", car);
  480.     }
  481.     else
  482.       wdoprintf(window,"  ");
  483.     if(j%4==(4-1))
  484.       wdoprintf(window," ");
  485.       }
  486.       wdoprintf(window,"  ");
  487.       for(j=0; j< 0x10;j++)
  488.       {
  489.     if(i*0x10+j<lng)
  490.     {
  491.       car=*((const unsigned char*)nom_dump+i*0x10+j);
  492.       if ((car<32)||(car >= 127))
  493.         wdoprintf(window,".");
  494.       else
  495.         wdoprintf(window,"%c",  car);
  496.     }
  497.     else
  498.       wdoprintf(window," ");
  499.       }
  500.     }
  501.     switch (wmenuSelect(window,INTER_DUMP_Y, INTER_DUMP_X, menuDump, 8, "PNQ", MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, menu))
  502.     {
  503.       case 'p':
  504.       case 'P':
  505.       case MENU_UP:
  506.     menu=0;
  507.     if(pos>0)
  508.       pos--;
  509.     break;
  510.       case 'n':
  511.       case 'N':
  512.       case MENU_DOWN:
  513.     menu=1;
  514.     if(pos<nbr_line-DUMP_MAX_LINES)
  515.       pos++;
  516.     break;
  517.       case KEY_PPAGE:
  518.     menu=0;
  519.     if(pos>DUMP_MAX_LINES-1)
  520.       pos-=DUMP_MAX_LINES-1;
  521.     else
  522.       pos=0;
  523.     break;
  524.       case KEY_NPAGE:
  525.     menu=1;
  526.     if(pos<nbr_line-DUMP_MAX_LINES-(DUMP_MAX_LINES-1))
  527.       pos+=DUMP_MAX_LINES-1;
  528.     else
  529.       pos=nbr_line-DUMP_MAX_LINES;
  530.     break;
  531.       case key_ESC:
  532.       case 'q':
  533.       case 'Q':
  534.     done = TRUE;
  535.     break;
  536.     }
  537.   } while(done==FALSE);
  538. }
  539.  
  540. void dump2(WINDOW *window, const void *dump_1, const void *dump_2, const unsigned int lng)
  541. {
  542.   unsigned int i,j;
  543.   unsigned int pos=0;
  544.   int done=0;
  545.   int menu=2;   /* default : quit */
  546.   unsigned int nbr_line;
  547.   struct MenuItem menuDump[]=
  548.   {
  549.     { 'P', "Previous",""},
  550.     { 'N', "Next","" },
  551.     { 'Q',"Quit","Quit dump section"},
  552.     { 0, NULL, NULL }
  553.   };
  554.   nbr_line=lng/0x08;
  555.   if(nbr_line%0x08)
  556.     nbr_line++;
  557.   /* write dump to log file*/
  558.   for (i=0; (i<nbr_line); i++)
  559.   {
  560.     ecrit_rapport("%04X ",i*0x08);
  561.     for(j=0; j<0x08;j++)
  562.     {
  563.       if(i*0x08+j<lng)
  564.       {
  565.     unsigned char car=*((const unsigned char *)dump_1+i*0x08+j);
  566.     ecrit_rapport("%02x", car);
  567.       }
  568.       else
  569.     ecrit_rapport("  ");
  570.       if(j%4==(4-1))
  571.     ecrit_rapport(" ");
  572.     }
  573.     ecrit_rapport("  ");
  574.     for(j=0; j<0x08;j++)
  575.     {
  576.       if(i*0x08+j<lng)
  577.       {
  578.     unsigned char car=*((const unsigned char*)dump_1+i*0x08+j);
  579.     if ((car<32)||(car >= 127))
  580.       ecrit_rapport(".");
  581.     else
  582.       ecrit_rapport("%c",  car);
  583.       }
  584.       else
  585.     ecrit_rapport(" ");
  586.     }
  587.     ecrit_rapport("  ");
  588.     for(j=0; j<0x08;j++)
  589.     {
  590.       if(i*0x08+j<lng)
  591.       {
  592.     unsigned char car=*((const unsigned char *)dump_2+i*0x08+j);
  593.     ecrit_rapport("%02x", car);
  594.       }
  595.       else
  596.     ecrit_rapport("  ");
  597.       if(j%4==(4-1))
  598.     ecrit_rapport(" ");
  599.     }
  600.     ecrit_rapport("  ");
  601.     for(j=0; j<0x08;j++)
  602.     {
  603.       if(i*0x08+j<lng)
  604.       {
  605.     unsigned char car=*((const unsigned char*)dump_2+i*0x08+j);
  606.     if ((car<32)||(car >= 127))
  607.       ecrit_rapport(".");
  608.     else
  609.       ecrit_rapport("%c",  car);
  610.       }
  611.       else
  612.     ecrit_rapport(" ");
  613.     }
  614.     ecrit_rapport("\n");
  615.   }
  616.   /* ncurses interface */
  617.   do
  618.   {
  619.     for (i=pos; (i<nbr_line)&&((i-pos)<DUMP_MAX_LINES); i++)
  620.     {
  621.       wmove(window,DUMP_Y+i-pos,DUMP_X);
  622.       wclrtoeol(window);
  623.       wdoprintf(window,"%04X ",i*0x08);
  624.       for(j=0; j<0x08;j++)
  625.       {
  626.     if(i*0x08+j<lng)
  627.     {
  628.       unsigned char car=*((const unsigned char*)dump_1+i*0x08+j);
  629.       wdoprintf(window,"%02x", car);
  630.     }
  631.     else
  632.       wdoprintf(window," ");
  633.     if(j%4==(4-1))
  634.       wdoprintf(window," ");
  635.       }
  636.       wdoprintf(window,"  ");
  637.       for(j=0; j<0x08;j++)
  638.       {
  639.     if(i*0x08+j<lng)
  640.     {
  641.       unsigned char car=*((const unsigned char*)dump_1+i*0x08+j);
  642.       if ((car<32)||(car >= 127))
  643.         wdoprintf(window,".");
  644.       else
  645.         wdoprintf(window,"%c",  car);
  646.     }
  647.     else
  648.       wdoprintf(window," ");
  649.       }
  650.       wdoprintf(window,"  ");
  651.       for(j=0; j<0x08;j++)
  652.       {
  653.     if(i*0x08+j<lng)
  654.     {
  655.       unsigned char car=*((const unsigned char*)dump_2+i*0x08+j);
  656.       wdoprintf(window,"%02x", car);
  657.       if(j%4==(4-1))
  658.         wdoprintf(window," ");
  659.     }
  660.     else
  661.       wdoprintf(window," ");
  662.       }
  663.       wdoprintf(window,"  ");
  664.       for(j=0; j<0x08;j++)
  665.       {
  666.     if(i*0x08+j<lng)
  667.     {
  668.       unsigned char car=*((const unsigned char*)dump_2+i*0x08+j);
  669.       if ((car<32)||(car >= 127))
  670.         wdoprintf(window,".");
  671.       else
  672.         wdoprintf(window,"%c",  car);
  673.     }
  674.     else
  675.       wdoprintf(window," ");
  676.       }
  677.     }
  678.     switch (wmenuSelect(window,INTER_DUMP_Y, INTER_DUMP_X, menuDump, 8, "PNQ", MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, menu))
  679.     {
  680.       case 'p':
  681.       case 'P':
  682.       case MENU_UP:
  683.     menu=0;
  684.     if(pos>0)
  685.       pos--;
  686.     break;
  687.       case 'n':
  688.       case 'N':
  689.       case MENU_DOWN:
  690.     menu=1;
  691.     if(pos<nbr_line-DUMP_MAX_LINES)
  692.       pos++;
  693.     break;
  694.       case KEY_PPAGE:
  695.     menu=0;
  696.     if(pos>DUMP_MAX_LINES-1)
  697.       pos-=DUMP_MAX_LINES-1;
  698.     else
  699.       pos=0;
  700.     break;
  701.       case KEY_NPAGE:
  702.     menu=1;
  703.     if(pos<nbr_line-DUMP_MAX_LINES-(DUMP_MAX_LINES-1))
  704.       pos+=DUMP_MAX_LINES-1;
  705.     else
  706.       pos=nbr_line-DUMP_MAX_LINES;
  707.     break;
  708.       case key_ESC:
  709.       case 'q':
  710.       case 'Q':
  711.     done = TRUE;
  712.     break;
  713.     }
  714.   } while(done==FALSE);
  715. }
  716.  
  717. int aff_buffer(const buffer_cmd_t cmd, const char *_format, ...)
  718. {
  719.   static char buffer[MAX_LINES][LINE_LENGTH+1];
  720.   static int nbr_lines=0;
  721.   va_list ap;
  722.   va_start(ap,_format);
  723.   switch(cmd)
  724.   {
  725.     case BUFFER_RESET:
  726.       {
  727.         int i;
  728.         nbr_lines=0;
  729.         for(i=0;i<MAX_LINES;i++)
  730.           memset(buffer[i],0,LINE_LENGTH+1);
  731.       }
  732.       break;
  733.     case BUFFER_ADD:
  734.       {
  735.         char tmp_line[BUFFER_LINE_LENGTH+1];
  736.         char *pos_in_tmp_line=tmp_line-1;
  737.         memset(tmp_line,'\0',sizeof(tmp_line));
  738.         vsnprintf(tmp_line,BUFFER_LINE_LENGTH,_format,ap);
  739.         while(pos_in_tmp_line!=NULL && (nbr_lines<MAX_LINES))
  740.         {
  741.           char *ret_ligne= strchr(++pos_in_tmp_line,'\n');
  742.           if(ret_ligne!=NULL)
  743.           {
  744.             strncat(buffer[nbr_lines],pos_in_tmp_line,
  745.                 ret_ligne-pos_in_tmp_line<LINE_LENGTH-strlen(buffer[nbr_lines])?ret_ligne-pos_in_tmp_line:LINE_LENGTH-strlen(buffer[nbr_lines]));
  746.             if(strlen(buffer[nbr_lines])>0)
  747.               nbr_lines++;
  748.           }
  749.           else
  750.           {
  751.             strncat(buffer[nbr_lines],pos_in_tmp_line,LINE_LENGTH-strlen(buffer[nbr_lines]));
  752.           }
  753.           pos_in_tmp_line=ret_ligne;
  754.         }
  755. /*    ecrit_rapport("aff_buffer %d =>%s<=\n",nbr_lines,tmp_line); */
  756.         if(nbr_lines>=MAX_LINES)
  757.         {
  758.           ecrit_rapport("aff_buffer too much lines =>%s<=\n",tmp_line);
  759.         }
  760.       }
  761.       break;
  762.     case BUFFER_DISPLAY:
  763.       {
  764.         int i;
  765.         int menu;
  766.         int pos=0;
  767.         int done=0;
  768.         WINDOW *window=*(WINDOW**)ap;
  769.         struct MenuItem menuBuffer[]=
  770.         {
  771.           { 'P', "Previous",""},
  772.           { 'N', "Next","" },
  773.           { 'Q',"Quit","Quit this section"},
  774.           { 'S',"Search!","Search deeper, try to find more partitions"},
  775.           { 'W', "Write","Write partition structure to disk"},
  776.           { 'O', "Org. BS","Copy boot sector over backup sector"},
  777.           { 'B', "Backup BS","Copy backup boot sector over boot sector"},
  778.           { 'R', "Rebuild BS","Rebuild boot sector"},
  779.           { 'D', "Dump","Dump boot sector and backup boot sector"},
  780.           { 0, NULL, NULL }
  781.         };
  782.         char options[20];
  783.         if(nbr_lines<=DUMP_MAX_LINES)
  784.         {
  785.           strncpy(options,"Q",sizeof(options));
  786.           menu=0;       /* default = quit */
  787.         }
  788.         else
  789.         {
  790.           strncpy(options,"PNQ",sizeof(options));
  791.           menu=1;       /* default = next */
  792.         }
  793.         strncat(options,_format,sizeof(options)-strlen(options));
  794.         if(buffer[nbr_lines][0]!='\0')
  795.           nbr_lines++;
  796.         /* to log file */
  797.         for(i=0;i<nbr_lines;i++)
  798.           ecrit_rapport("%s\n",buffer[i]);
  799.         /* curses interface */
  800.         do
  801.         {
  802.           for (i=pos; (i<nbr_lines)&&((i-pos)<DUMP_MAX_LINES); i++)
  803.           {
  804.             wmove(window,DUMP_Y+i-pos,DUMP_X);
  805.             wclrtoeol(window);
  806.             wdoprintf(window,"%s",buffer[i]);
  807.           }
  808.           
  809.           switch (wmenuSelect(window,INTER_DUMP_Y, INTER_DUMP_X, menuBuffer, 8, options, MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, menu))
  810.           {
  811.             case 'p':
  812.             case 'P':
  813.             case MENU_UP:
  814.               menu=0;
  815.               if(pos>0)
  816.             pos--;
  817.               break;
  818.             case 'n':
  819.             case 'N':
  820.             case MENU_DOWN:
  821.               menu=1;
  822.               if(pos<nbr_lines-DUMP_MAX_LINES)
  823.             pos++;
  824.               break;
  825.             case KEY_PPAGE:
  826.               menu=0;
  827.               if(pos>DUMP_MAX_LINES-1)
  828.             pos-=DUMP_MAX_LINES-1;
  829.               else
  830.             pos=0;
  831.               break;
  832.             case KEY_NPAGE:
  833.               menu=1;
  834.               if(pos<nbr_lines-DUMP_MAX_LINES-(DUMP_MAX_LINES)-1)
  835.             pos+=DUMP_MAX_LINES-1;
  836.               else
  837.             pos=nbr_lines-DUMP_MAX_LINES>0?nbr_lines-DUMP_MAX_LINES:0;
  838.               break;
  839.             case 's':
  840.             case 'S':
  841.               if(strchr(options,'S')!=NULL)
  842.               {
  843.             va_end(ap);
  844.             return 2;
  845.               }
  846.               break;
  847.             case 'o':
  848.             case 'O':
  849.               if(strchr(options,'O')!=NULL)
  850.               {
  851.             va_end(ap);
  852.             return 1;
  853.               }
  854.               break;
  855.             case 'b':
  856.             case 'B':
  857.               if(strchr(options,'B')!=NULL)
  858.               {
  859.             va_end(ap);
  860.             return 2;
  861.               }
  862.               break;
  863.             case 'r':
  864.             case 'R':
  865.               if(strchr(options,'R')!=NULL)
  866.               {
  867.             va_end(ap);
  868.             return 3;
  869.               }
  870.               break;
  871.             case 'd':
  872.             case 'D':
  873.               if(strchr(options,'D')!=NULL)
  874.               {
  875.             va_end(ap);
  876.             return 4;
  877.               }
  878.               break;
  879.             case 'w':
  880.             case 'W':
  881.               if(strchr(options,'W')!=NULL)
  882.               {
  883.             va_end(ap);
  884.             return 1;
  885.               }
  886.               break;
  887.             case key_ESC:
  888.             case 'q':
  889.             case 'Q':
  890.               done = TRUE;
  891.               break;
  892.           }
  893.         } while(done!=TRUE);
  894.       }
  895.       break;
  896.     case BUFFER_SHOW:
  897.       {
  898.         int i;
  899.         int pos=nbr_lines-DUMP_MAX_LINES<0?0:nbr_lines-DUMP_MAX_LINES;
  900.         if(buffer[nbr_lines][0]!='\0')
  901.           nbr_lines++;
  902.         /* curses interface */
  903.         for (i=pos; (i<nbr_lines)&&((i-pos)<DUMP_MAX_LINES); i++)
  904.         {
  905.           wmove(stdscr,DUMP_Y+1+i-pos,DUMP_X);
  906.           wclrtoeol(stdscr);
  907.           wdoprintf(stdscr,"%s",buffer[i]);
  908.         }
  909.         wrefresh(stdscr);
  910.       }
  911.       break;
  912.     case BUFFER_WRITE:
  913.       {
  914.         int i;
  915.         if(buffer[nbr_lines][0]!='\0')
  916.           nbr_lines++;
  917.         /* to log file */
  918.         for(i=0;i<nbr_lines;i++)
  919.         {
  920.           printf("%s\n",buffer[i]);
  921.           ecrit_rapport("%s\n",buffer[i]);
  922.         }
  923.       }
  924.       break;
  925.   }
  926.   va_end(ap);
  927.   return 0;
  928. }
  929.  
  930. /*
  931. part_num  2
  932. PLEX      1
  933. part_type ...
  934. CHS 5+1+3+1+2=12
  935. size      9
  936. part_name EXT2 16, FAT 11
  937.  
  938. part_num PLEX part_type CHS CHS size [part_name]
  939. 2       1  1 1       x 1 121 121  9 11      16 1
  940. 2+1+1+1+x+1+12+1+12+1+9+1+1+16+1=60+x
  941.  * */
  942.  
  943. void aff_part_buffer(const aff_part_type_t newline,const t_param_disk *disk_car,const t_diskext *partition)
  944. {
  945.   switch(newline)
  946.   {
  947.     case AFF_PART_NL:
  948.       aff_buffer(BUFFER_ADD,"\n   ");
  949.       break;
  950.     case AFF_PART_ORDER:
  951.       if((partition->status!=STATUS_EXT_IN_EXT) && partition->order!=0)
  952.     aff_buffer(BUFFER_ADD,"%2d ", partition->order);
  953.       else
  954.     aff_buffer(BUFFER_ADD,"   ");
  955.       break;
  956.     case AFF_PART_NONL:
  957.     case AFF_PART_SHORT:
  958.       break;
  959.   }
  960.   if(newline!=AFF_PART_SHORT)
  961.   {
  962.     switch(partition->status)
  963.     {
  964.       case STATUS_PRIM:           aff_buffer(BUFFER_ADD,"P"); break;
  965.       case STATUS_PRIM_BOOT:      aff_buffer(BUFFER_ADD,"*"); break;
  966.       case STATUS_EXT:            aff_buffer(BUFFER_ADD,"E"); break;
  967.       case STATUS_EXT_IN_EXT:     aff_buffer(BUFFER_ADD,"X"); break;
  968.       case STATUS_LOG:            aff_buffer(BUFFER_ADD,"L"); break;
  969.       case STATUS_DELETED:        aff_buffer(BUFFER_ADD,"D"); break;
  970.     }
  971.   }
  972.   if(nom_os[partition->part_type]!=NULL)
  973.     aff_buffer(BUFFER_ADD," %-20s ",nom_os[partition->part_type]);
  974.   else
  975.     aff_buffer(BUFFER_ADD," Sys=%02X\t\t\t  ", partition->part_type);
  976.   aff_CHS_from_LBA_buffer(disk_car,partition->lba);
  977.   aff_CHS_from_LBA_buffer(disk_car,partition->lba+partition->part_size-1);
  978.   aff_buffer(BUFFER_ADD,"%10lu", partition->part_size);
  979.   if(partition->name[0]!='\0')
  980.     aff_buffer(BUFFER_ADD," [%s]",partition->name);
  981.   if(newline==AFF_PART_ORDER || newline==AFF_PART_SHORT)
  982.     aff_buffer(BUFFER_ADD,"\n");
  983. }
  984.  
  985. void aff_entry(const struct partition_dos *entree)
  986. {
  987.   if(nom_os[entree->sys_ind]!=NULL)
  988.     wdoprintf(stdscr,"\n %-20s ",nom_os[entree->sys_ind]);
  989.   else
  990.     wdoprintf(stdscr,"\n Sys=%02X\t\t\t  ", entree->sys_ind);
  991.   wdoprintf(stdscr,"%4u %3u %2u"
  992.      " %4u %3u %2u"
  993.      " %10u"
  994.      " %10u",
  995.       s_cyl(entree),s_head(entree),s_sect(entree),
  996.       e_cyl(entree),e_head(entree),e_sect(entree),
  997.       get_start_sect(entree),get_nr_sects(entree));
  998. }
  999.  
  1000. void aff_entry_rapport(const struct partition_dos *entree)
  1001. {
  1002.   if(nom_os[entree->sys_ind]!=NULL)
  1003.     ecrit_rapport(" %-20s ",nom_os[entree->sys_ind]);
  1004.   else
  1005.     ecrit_rapport(" Sys=%02X\t\t\t  ", entree->sys_ind);
  1006.   ecrit_rapport("%4u %3u %2u"
  1007.      " %4u %3u %2u"
  1008.      " %10u"
  1009.      " %10u\n",
  1010.       s_cyl(entree),s_head(entree),s_sect(entree),
  1011.       e_cyl(entree),e_head(entree),e_sect(entree),
  1012.       get_start_sect(entree),get_nr_sects(entree));
  1013. }
  1014.  
  1015. void aff_CHS_rapport(const t_CHS * CHS)
  1016. {
  1017.   ecrit_rapport("%5u %3u %2u ", CHS->cylinder, CHS->head, CHS->sector);
  1018. }
  1019.  
  1020. void aff_CHS(const t_CHS * CHS)
  1021. {
  1022.   wdoprintf(stdscr,"%5u %3u %2u ", CHS->cylinder, CHS->head, CHS->sector);
  1023. }
  1024.  
  1025. void aff_CHS_buffer(const t_CHS * CHS)
  1026. {
  1027.   aff_buffer(BUFFER_ADD,"%5u %3u %2u ", CHS->cylinder, CHS->head, CHS->sector);
  1028. }
  1029.  
  1030. static void aff_CHS_from_LBA(WINDOW *window, const t_param_disk *disk_car, dword hd_offset)
  1031. {
  1032.   wdoprintf(window,"%5u %3u %2u ", LBA2cylinder(disk_car,hd_offset), LBA2head(disk_car,hd_offset),LBA2sector(disk_car,hd_offset));
  1033. }
  1034.  
  1035. static void aff_CHS_from_LBA_buffer(const t_param_disk *disk_car, dword hd_offset)
  1036. {
  1037.   aff_buffer(BUFFER_ADD,"%5u %3u %2u ", LBA2cylinder(disk_car,hd_offset), LBA2head(disk_car,hd_offset),LBA2sector(disk_car,hd_offset));
  1038. }
  1039.  
  1040. static void aff_CHS_from_LBA_rapport(const t_param_disk *disk_car, dword hd_offset)
  1041. {
  1042.   ecrit_rapport("%5u %3u %2u ", LBA2cylinder(disk_car,hd_offset), LBA2head(disk_car,hd_offset),LBA2sector(disk_car,hd_offset));
  1043. }
  1044.  
  1045. void aff_part_rapport(const t_param_disk *disk_car,const t_diskext *partition)
  1046. {
  1047.   if((partition->status!=STATUS_EXT_IN_EXT) && (partition->order!=0))
  1048.     ecrit_rapport("%2d ", partition->order);
  1049.   else
  1050.     ecrit_rapport("   ");
  1051.   switch(partition->status)
  1052.   {
  1053.     case STATUS_PRIM:           ecrit_rapport("P"); break;
  1054.     case STATUS_PRIM_BOOT:      ecrit_rapport("*"); break;
  1055.     case STATUS_EXT:            ecrit_rapport("E"); break;
  1056.     case STATUS_EXT_IN_EXT:     ecrit_rapport("X"); break;
  1057.     case STATUS_LOG:            ecrit_rapport("L"); break;
  1058.     case STATUS_DELETED:        ecrit_rapport("D"); break;
  1059.   }
  1060.   if(nom_os[partition->part_type]!=NULL)
  1061.     ecrit_rapport(" %-20s ",nom_os[partition->part_type]);
  1062.   else
  1063.     ecrit_rapport(" Sys=%02X\t\t\t  ", partition->part_type);
  1064.   aff_CHS_from_LBA_rapport(disk_car,partition->lba);
  1065.   aff_CHS_from_LBA_rapport(disk_car,partition->lba+partition->part_size-1);
  1066.   ecrit_rapport("%10lu", partition->part_size);
  1067.   if(partition->name[0]!='\0')
  1068.     ecrit_rapport(" [%s]",partition->name);
  1069.   if(partition->info[0]!='\0')
  1070.     ecrit_rapport("\n     %s",partition->info);
  1071.   ecrit_rapport("\n");
  1072. }
  1073.  
  1074. void aff_part(WINDOW *window,const aff_part_type_t newline,const t_param_disk *disk_car,const t_diskext *partition)
  1075. {
  1076.   switch(newline)
  1077.   {
  1078.     case AFF_PART_NL:
  1079.       wdoprintf(window,"\n   ");
  1080.       break;
  1081.     case AFF_PART_ORDER:
  1082.       if(partition->status!=STATUS_EXT_IN_EXT)
  1083.     wdoprintf(window,"%2d ", partition->order);
  1084.       else
  1085.     wdoprintf(window,"   ");
  1086.       break;
  1087.     case AFF_PART_NONL:
  1088.     case AFF_PART_SHORT:
  1089.       break;
  1090.   }
  1091.   if(newline!=AFF_PART_SHORT)
  1092.   {
  1093.     switch(partition->status)
  1094.     {
  1095.       case STATUS_PRIM:           wdoprintf(window,"P"); break;
  1096.       case STATUS_PRIM_BOOT:      wdoprintf(window,"*"); break;
  1097.       case STATUS_EXT:            wdoprintf(window,"E"); break;
  1098.       case STATUS_EXT_IN_EXT:     wdoprintf(window,"X"); break;
  1099.       case STATUS_LOG:            wdoprintf(window,"L"); break;
  1100.       case STATUS_DELETED:        wdoprintf(window,"D"); break;
  1101.     }
  1102.   }
  1103.   if(nom_os[partition->part_type]!=NULL)
  1104.     wdoprintf(window," %-20s ",nom_os[partition->part_type]);
  1105.   else
  1106.     wdoprintf(window," Sys=%02X\t\t\t  ", partition->part_type);
  1107.   aff_CHS_from_LBA(window,disk_car,partition->lba);
  1108.   aff_CHS_from_LBA(window,disk_car,partition->lba+partition->part_size-1);
  1109.   wdoprintf(window,"%10lu", partition->part_size);
  1110.   if(partition->name[0]!='\0')
  1111.     wdoprintf(window," [%s]",partition->name);
  1112. }
  1113.  
  1114. void aff_LBA2CHS(const t_param_disk *disk_car, const dword pos_LBA)
  1115. {
  1116.   dword tmp;
  1117.   dword cylinder, head, sector;
  1118.   tmp=disk_car->CHS.sector;
  1119.   sector=(pos_LBA%tmp)+1;
  1120.   tmp=pos_LBA/tmp;
  1121.   cylinder=tmp/(disk_car->CHS.head+1);
  1122.   head=tmp%(disk_car->CHS.head+1);
  1123.   wdoprintf(stdscr,"%lu/%lu/%lu", cylinder,head,sector);
  1124. }
  1125.  
  1126. void aff_LBA2CHS_rapport(const t_param_disk *disk_car, const dword pos_LBA)
  1127. {
  1128.   dword tmp;
  1129.   dword cylinder, head, sector;
  1130.   tmp=disk_car->CHS.sector;
  1131.   sector=(pos_LBA%tmp)+1;
  1132.   tmp=pos_LBA/tmp;
  1133.   cylinder=tmp/(disk_car->CHS.head+1);
  1134.   head=tmp%(disk_car->CHS.head+1);
  1135.   ecrit_rapport("%lu/%lu/%lu", cylinder,head,sector);
  1136. }
  1137.  
  1138.  
  1139. void interface_list(t_param_disk *disk_car, const int debug,const int test_recovery)
  1140. { /* log */
  1141.   t_list_part *list_part;
  1142.   ecrit_rapport("\nAnalyse ");
  1143.   ecrit_rapport("%s",disk_car->description(disk_car));
  1144.   printf("%s",disk_car->description(disk_car));
  1145.   list_part=read_part(disk_car, debug);
  1146.   aff_buffer(BUFFER_WRITE,"Q");
  1147.   if(test_recovery)
  1148.   {
  1149.     t_list_part *element;
  1150.     ecrit_rapport("rebuild_FAT_BS()\n");
  1151.     for(element=list_part;element!=NULL;element=element->next)
  1152.     {
  1153.       if(is_fat(element->part->part_type))        /* do not use upart_type */
  1154.       {
  1155.     aff_part_rapport(disk_car,element->part);
  1156.     rebuild_FAT_BS(disk_car,element->part,debug,0,0);    /* dump_ind */
  1157.       }
  1158.     }
  1159.   }
  1160.   delete_list_part(list_part);
  1161. }
  1162.  
  1163. int ask_YN(WINDOW *window,const char* msg)
  1164. {
  1165.   char res;
  1166.   wdoprintf(window,"%s",msg);
  1167.   wrefresh(window);
  1168.   do
  1169.   {
  1170.     res=toupper(wgetch(window));
  1171.   } while((res!=c_NO)&(res!=c_YES));
  1172.   wdoprintf(window,"%c\n",res);
  1173.   return (res==c_YES);
  1174. }
  1175.  
  1176. int ask_confirmation(const char*msg)
  1177. {
  1178.   int res;
  1179.   WINDOW *window=newwin(0,0,0,0);    /* full screen */
  1180.   aff_copy(window);
  1181.   res=ask_YN(window,msg);
  1182.   delwin(window);
  1183. #ifdef DJGPP
  1184.   wredrawln(stdscr,0,stdscr->_maxy);    /* redrawwin def is boggus in pdcur24 */
  1185. #else
  1186.   redrawwin(stdscr);    /* stdscr has been corrupted by window */
  1187. #endif
  1188.   return res;
  1189. }
  1190.  
  1191. int wdoprintf(WINDOW *window, const char *_format, ...)
  1192. {
  1193.   char res[800];
  1194.   va_list ap;
  1195.   va_start(ap,_format);
  1196.   vsnprintf(res,sizeof(res),_format,ap);
  1197.   va_end(ap);
  1198.   return waddstr(window,res);
  1199. }
  1200.  
  1201. int display_message(const char*msg)
  1202. {
  1203.   int pipo=0;
  1204.   static struct MenuItem menuGeometry[]=
  1205.   {
  1206.     { 'O', "Ok", "" },
  1207.     { 0, NULL, NULL }
  1208.   };
  1209.   WINDOW *window=newwin(0,0,0,0);    /* full screen */
  1210.   aff_copy(window);
  1211.   mvwaddstr(window,5,0,msg);
  1212.   wmenuSimple(window,menuGeometry, pipo);
  1213.   delwin(window);
  1214. #ifdef DJGPP
  1215.   wredrawln(stdscr,0,stdscr->_maxy);    /* redrawwin def is boggus in pdcur24 */
  1216. #else
  1217.   redrawwin(stdscr);    /* stdscr has been corrupted by window */
  1218. #endif
  1219.   ecrit_rapport("%s",msg);
  1220.   return 0;
  1221. }
  1222.  
  1223. int write_MBR_code(t_param_disk *disk_car)
  1224. {
  1225.   if(ask_YN(stdscr,msg_WRITE_MBR_CODE)!=0 && ask_confirmation("Write a new copy of MBR code, confirm ? (Y/N)")!=0)
  1226.   {
  1227.     unsigned char buffer[SECTOR_SIZE];
  1228.     if(read_MBR(disk_car,&buffer)!=0)
  1229.       return 1;
  1230.     write_MBR_code_aux(buffer);
  1231.     return write_MBR(disk_car,&buffer);
  1232.   }
  1233.   return 0;
  1234. }
  1235.  
  1236. int write_clean_table(t_param_disk *disk_car)
  1237. {
  1238.   unsigned char buffer[SECTOR_SIZE];
  1239.   if(ask_YN(stdscr,msg_WRITE_CLEAN_TABLE)!=0 && ask_confirmation("Clear partition table, confirm ? (Y/N)")!=0)
  1240.   {
  1241.     if(read_MBR(disk_car,&buffer)!=0)
  1242.       return 1;
  1243.     memset(&buffer[TAB_PART],0,0x40);
  1244.     return write_MBR(disk_car,&buffer);
  1245.   }
  1246.   return 0;
  1247. }
  1248.  
  1249. int do_curses_testdisk(int debug,int paranoid,int dump_ind, int fast_mode,int align,int do_analyse, const t_list_disk *list_disk)
  1250. {
  1251.   int command;
  1252.   int done=0;
  1253.   int recover_cih=0;
  1254.   int allow_partial_last_cylinder=0;
  1255.   int ask_part_order=0;
  1256.   int halt_on_errors=1;
  1257.   int max_ext=0;
  1258.   const t_list_disk *element_disk;
  1259.   const t_list_disk *current_disk=list_disk;
  1260.   static struct MenuItem menuMain[]=
  1261.   {
  1262.     {'A',"Analyse","Analyse current partition structure and search for lost partitions"},
  1263.     {'D',"Delete","Delete all data in the partition table"},
  1264.     {'C',"MBR Code","Write the Classic MBR code to first sector"},
  1265.     {'G',"Geometry", "Change disk geometry (expert only)" },
  1266.     {'O',"Options","Modify options"},
  1267.     {'E',"Editor","Basic disk editor"},
  1268.     {'T',"Advanced","Advanced boot recovery"},
  1269.     {'Q',"Quit","Quit program"},
  1270.     {0,NULL,NULL}
  1271.   };
  1272.   if(list_disk==NULL)
  1273.     return 0;
  1274. /* use_env(TRUE); */
  1275.   initscr();
  1276.   noecho();
  1277.   keypad(stdscr, TRUE); /* Need it to get arrow key */
  1278. #ifndef DJGPP
  1279.   nonl(); /*don't use for Dos version but enter will work with it... dilema */
  1280. #endif
  1281.   crmode();
  1282.   /*  intrflush(stdscr, FALSE); */
  1283.   cbreak();
  1284.   if(LINES<25)
  1285.   {
  1286.     ecrit_rapport("Terminal has only %u lines\n",LINES);
  1287.     nl();
  1288.     endwin();
  1289.     return 1;
  1290.   }
  1291.   /* ncurses interface */
  1292.   while(done==0)
  1293.   {
  1294.     aff_copy_full(stdscr);
  1295.     wmove(stdscr,5,0);
  1296.     for(element_disk=list_disk;element_disk!=NULL;element_disk=element_disk->next)
  1297.     {
  1298.       if(element_disk!=current_disk)
  1299.     wdoprintf(stdscr,"%s",element_disk->disk->description(element_disk->disk));
  1300.       else
  1301.       {
  1302.     wstandout(stdscr);
  1303.     wdoprintf(stdscr,"%s",element_disk->disk->description(element_disk->disk));
  1304.     wstandend(stdscr);
  1305.       }
  1306.     }
  1307.     current_disk->disk->halt_on_errors=halt_on_errors;
  1308.     command = toupper(wmenuSelect(stdscr,INTER_MAIN_Y, INTER_MAIN_X, menuMain, 8,
  1309.       "AGDCOTQ", MENU_HORIZ | MENU_BUTTON | MENU_ACCEPT_OTHERS, 0));
  1310.     /* e for editor will be added when the editor will be better */
  1311.     switch(command)
  1312.     {
  1313.       case 'G':
  1314.     change_geometry(current_disk->disk);
  1315.     break;
  1316.       case 'D':
  1317.     wmove(stdscr,INTER_MAIN_Y,INTER_MAIN_X);
  1318.     write_clean_table(current_disk->disk);
  1319.     break;
  1320.       case 'C':
  1321.     wmove(stdscr,INTER_MAIN_Y,INTER_MAIN_X);
  1322.     write_MBR_code(current_disk->disk);
  1323.     break;
  1324.       case 'A':
  1325.     if(do_analyse)
  1326.       interface_analyse(current_disk->disk,debug);
  1327.     interface_recovery(current_disk->disk,paranoid,debug, dump_ind, fast_mode,align,recover_cih,ask_part_order,max_ext);
  1328.     break;
  1329.       case 'T':    /* Test */
  1330.     interface_adv(current_disk->disk, debug, dump_ind);
  1331.     break;
  1332.       case 'E':
  1333.     interface_editor(current_disk->disk);
  1334.     break;
  1335.       case 'Q':
  1336.     done = 1;
  1337.     break;
  1338.       case 'O':
  1339.     {
  1340.       int old_allow_partial_last_cylinder=allow_partial_last_cylinder;
  1341.       interface_options(¶noid,&dump_ind,&fast_mode,&align,&recover_cih,&allow_partial_last_cylinder,&ask_part_order,&halt_on_errors,&max_ext);
  1342.       if(old_allow_partial_last_cylinder!=allow_partial_last_cylinder)
  1343.         hd_parse_bis(list_disk,allow_partial_last_cylinder);
  1344.     }
  1345.     break;
  1346.       case MENU_UP:
  1347.     if(current_disk->prev!=NULL)
  1348.       current_disk=current_disk->prev;
  1349.     break;
  1350.       case MENU_DOWN:
  1351.     if(current_disk->next!=NULL)
  1352.       current_disk=current_disk->next;
  1353.     break;
  1354. #ifdef DEBUG
  1355.       default:
  1356.     wmove(stdscr,10,0);
  1357.     wdoprintf(stdscr,"key %03X %d", command, command);
  1358.     wrefresh(stdscr);
  1359.     break;
  1360. #endif
  1361.     }
  1362.   }
  1363.   wclear(stdscr);
  1364.   wrefresh(stdscr);
  1365.   nl();
  1366.   endwin();
  1367.   ecrit_rapport("\n");
  1368.   return 0;
  1369. }
  1370.  
  1371. void interface_analyse(t_param_disk *disk_car, const int debug)
  1372. {
  1373.   /* log */
  1374.   ecrit_rapport("\nAnalyse ");
  1375.   ecrit_rapport("%s",disk_car->description(disk_car));
  1376.   /* ncurses interface */
  1377.   aff_copy(stdscr);
  1378.   mvwaddstr(stdscr,23,0,msg_PART_TYPE);
  1379.   wmove(stdscr,4,0);
  1380.   wdoprintf(stdscr,"%s",disk_car->description(disk_car));
  1381.   mvwaddstr(stdscr,5,0,"Check current partition structure");
  1382.   wmove(stdscr,6,0);
  1383.   wrefresh(stdscr);
  1384.   delete_list_part(read_part(disk_car, debug));
  1385.   ecrit_rapport("Current partitions:\n");
  1386.   aff_buffer(BUFFER_DISPLAY,"Q",stdscr);
  1387. }
  1388.  
  1389. int interface_write(t_param_disk *disk_car,t_list_part *list_part,const int can_search_deeper)
  1390. {
  1391.   t_list_part *parts;
  1392.   ecrit_rapport("\ninterface_write()\n");
  1393.   aff_copy(stdscr);
  1394.   wmove(stdscr,4,0);
  1395.   wdoprintf(stdscr,"%s",disk_car->description(disk_car));
  1396.   wmove(stdscr,5,0);
  1397.   aff_buffer(BUFFER_RESET,"Q");
  1398.   mvwaddstr(stdscr,6,0,msg_PART_HEADER_WRITE);
  1399.   for(parts=list_part;parts!=NULL;parts=parts->next)
  1400.     if(parts->part->status!=STATUS_LOG)
  1401.       aff_part_buffer(AFF_PART_ORDER,disk_car,parts->part);
  1402.   for(parts=list_part;parts!=NULL;parts=parts->next)
  1403.     if(parts->part->status==STATUS_LOG)
  1404.       aff_part_buffer(AFF_PART_ORDER,disk_car,parts->part);
  1405.   return aff_buffer(BUFFER_DISPLAY,can_search_deeper?"SW":"W",stdscr);
  1406. }
  1407.  
  1408. static void interface_options(int *paranoid,int *dump_ind,int *fast_mode,int *align,int *recover_cih, int *allow_partial_last_cylinder,int *ask_part_order,int *halt_on_errors, int *max_ext)
  1409. {
  1410. /* paranoid: search in partition
  1411.  * dump_ind dump sector Y/N
  1412.  * fast_mode Partitions are aligned on cylinder boundary Y/N
  1413.  * */
  1414.   int done = FALSE;
  1415.   int menu = 9;
  1416.   /* ncurses interface */
  1417.   while (done==FALSE) {
  1418.     int car;
  1419.     struct MenuItem menuOptions[]=
  1420.     {
  1421.       { 'P', NULL, "Search all partitions" },
  1422.       { 'D',NULL,"Dump essential sectors" },
  1423.       { 'C',NULL,"Partitions are aligned on cylinder boundary" },
  1424.       { 'F',NULL,"Don't check every hard disk head" },
  1425.       { 'T',NULL,"WARNING: ONLY WORKS WITH  FAT  PARTITION TYPES" },
  1426.       { 'A',NULL,""},
  1427.       { 'O',NULL,""},
  1428.       { 'E',NULL,"Halt on Disk I/O errors" },
  1429.       { 'M',NULL,""},
  1430.       { 'Q',"Quit","Return to main menu"},
  1431.       { 0, NULL, NULL }
  1432.     };
  1433.     menuOptions[0].name=*paranoid?"Paranoid : Yes":"Paranoid : No";
  1434.     menuOptions[1].name=*dump_ind?"Dump : Yes":"Dump : No";
  1435.     menuOptions[2].name=*align?"Cylinder boundary : Yes":"Cylinder boundary : No";
  1436.     switch(*fast_mode)
  1437.     {
  1438.       case 0:
  1439.         menuOptions[3].name="Mode : Fast";
  1440.         break;
  1441.       case 1:
  1442.         menuOptions[3].name="Mode : Medium";
  1443.         break;
  1444.       default:
  1445.         menuOptions[3].name="Mode : Slow";
  1446.         break;
  1447.     }
  1448.     menuOptions[4].name=*recover_cih?"Recover from CIH virus : Yes":"Recover from CIH virus : No";
  1449.     menuOptions[5].name=*allow_partial_last_cylinder?"Allow partial last cylinder : Yes":"Allow partial last cylinder : No";
  1450.     menuOptions[6].name=*ask_part_order?"Ask partition order : Yes":"Ask partition order : No";
  1451.     menuOptions[7].name=*halt_on_errors?"Halt on errors : Yes":"Halt on errors : No";
  1452.     menuOptions[8].name=*max_ext?"Maximize extended part : Yes":"Maximize extended part : No";
  1453. /*    car=toupper( wmenuSelect(stdscr,INTER_OPTION_Y, INTER_OPTION_X, menuOptions, 0, "PDCFAOEMQ", MENU_VERT, menu)); */
  1454.     car=toupper( wmenuSelect(stdscr,INTER_OPTION_Y, INTER_OPTION_X, menuOptions, 0, "DCAOEMQ", MENU_VERT, menu));
  1455.     switch(car)
  1456.     {
  1457.       case 'P':
  1458.         *paranoid=!*paranoid;
  1459.         menu=0;
  1460.         break;
  1461.       case 'D':
  1462.         *dump_ind=!*dump_ind;
  1463.         menu=1;
  1464.         break;
  1465.       case 'C':
  1466.         *align=!*align;
  1467.         menu=2;
  1468.         break;
  1469.       case 'F':
  1470.         if(*fast_mode<2)
  1471.           (*fast_mode)++;
  1472.         else
  1473.           *fast_mode=0;
  1474.         menu=3;
  1475.         break;
  1476.       case 'T':
  1477.         *recover_cih=!*recover_cih;
  1478.         menu=4;
  1479.         break;
  1480.       case 'A':
  1481.         *allow_partial_last_cylinder=!*allow_partial_last_cylinder;
  1482.         menu=5;
  1483.         break;
  1484.       case 'O':
  1485.         *ask_part_order=!*ask_part_order;
  1486.         menu=6;
  1487.         break;
  1488.       case 'E':
  1489.         *halt_on_errors=!*halt_on_errors;
  1490.         menu=7;
  1491.         break;
  1492.       case 'M':
  1493.         *max_ext=!*max_ext;
  1494.         menu=8;
  1495.         break;
  1496.       case key_ESC:
  1497.       case 'Q':
  1498.         done = TRUE;
  1499.         break;
  1500.     }
  1501.   }
  1502.   /* write new options to log file */
  1503.   ecrit_rapport("New options :\n Paranoid : %s\n Dump : %s\n Cylinder boudary : %s\n fast_mode=%d(0=fast)\n Allow partial last cylinder : %s\n Ask partition order : %s\n Halt on errors : %s\n Recover from CIH virus : %s\n Maximize extended part : %s\n",
  1504.     *paranoid?"Yes":"No",
  1505.     *dump_ind?"Yes":"No",
  1506.     *align?"Yes":"No",
  1507.     *fast_mode,
  1508.     *allow_partial_last_cylinder?"Yes":"No",
  1509.     *ask_part_order?"Yes":"No",
  1510.     *halt_on_errors?"Yes":"No",
  1511.     *recover_cih?"Yes":"No",
  1512.     *max_ext?"Yes":"No");
  1513. }
  1514.  
  1515. t_list_part *ask_structure(t_param_disk *disk_car,t_list_part *list_part, const int debug)
  1516. {
  1517.   int quit=0;
  1518.   int offset=0;
  1519.   int pos_num=0;
  1520.   t_list_part *pos=list_part;
  1521.   int rewrite=1;
  1522.   do
  1523.   {
  1524.     int i;
  1525.     t_list_part *parts;
  1526.     int car;
  1527.     if(rewrite)
  1528.     {
  1529.       aff_copy(stdscr);
  1530.       wmove(stdscr,4,0);
  1531.       wdoprintf(stdscr,"%s",disk_car->description(disk_car));
  1532.       mvwaddstr(stdscr,23,0,msg_PART_TYPE);
  1533.       mvwaddstr(stdscr,5,0,msg_CHOOSE_PART_TYPE);
  1534.       mvwaddstr(stdscr,6,0,msg_CHOOSE_PART_TYPE_END);
  1535.       mvwaddstr(stdscr,7,0,msg_PART_HEADER2);
  1536.       rewrite=0;
  1537.     }
  1538.     for(i=0,parts=list_part;(parts!=NULL) && (i<offset);parts=parts->next,i++);
  1539.     for(i=offset;(parts!=NULL) &&((i-offset)<INTER_STRUCTURE);i++,parts=parts->next)
  1540.     {
  1541.       wmove(stdscr,8+i-offset,0);
  1542.       wclrtoeol(stdscr);    /* before addstr for BSD compatibility */
  1543.       if(parts==pos)
  1544.       {
  1545.     wstandout(stdscr);
  1546.     aff_part(stdscr,AFF_PART_NONL,disk_car,parts->part);
  1547.     wstandend(stdscr);
  1548.     wmove(stdscr,24,0);
  1549.     wclrtoeol(stdscr);    /* before addstr for BSD compatibility */
  1550.     waddstr(stdscr,parts->part->info);
  1551.       } else
  1552.       {
  1553.     aff_part(stdscr,AFF_PART_NONL,disk_car,parts->part);
  1554.       }
  1555.     }
  1556.     if(test_structure(list_part)!=0)
  1557.       mvwaddstr(stdscr,22,0,msg_STRUCT_BAD);
  1558.     else
  1559.       mvwaddstr(stdscr,22,0,msg_STRUCT_OK);
  1560.     wmove(stdscr,22,15);
  1561.     wclrtoeol(stdscr);    /* before addstr for BSD compatibility */
  1562.     waddstr(stdscr,"Keys a: add partition");
  1563.     if(list_part!=NULL)
  1564.     {
  1565.       waddstr(stdscr,", T: change type");
  1566.       switch(pos->part->upart_type)
  1567.       {
  1568.     case UP_EXT2:
  1569.     case UP_EXT3:
  1570.     case UP_RFS:
  1571.     case UP_RFS2:
  1572.     case UP_FAT12:
  1573.     case UP_FAT16:
  1574.     case UP_FAT32:
  1575.     case UP_NTFS:
  1576.       waddstr(stdscr,", P: list files");
  1577.       break;
  1578.     default:
  1579.       break;
  1580.       }
  1581.     }
  1582.     wrefresh(stdscr);
  1583.     car=wgetch(stdscr);
  1584.     switch(car)
  1585.     {
  1586.       case 'q':
  1587.       case '\r':
  1588.       case '\n':
  1589.       case KEY_ENTER:
  1590. #ifdef PADENTER
  1591.       case PADENTER:
  1592. #endif
  1593.       case 'M':
  1594.     quit=1;
  1595.     break;
  1596.     }
  1597.     switch(car)
  1598.     {
  1599.       case KEY_UP:
  1600.     if(list_part!=NULL)
  1601.     {
  1602.       only_one_bootable(list_part,pos);
  1603.       if(pos->prev!=NULL)
  1604.       {
  1605.         pos=pos->prev;
  1606.         pos_num--;
  1607.       }
  1608.       if(pos_num<offset)
  1609.         offset--;
  1610.     }
  1611.     break;
  1612.       case KEY_DOWN:
  1613.     if(list_part!=NULL)
  1614.     {
  1615.       only_one_bootable(list_part,pos);
  1616.       if(pos->next!=NULL)
  1617.       {
  1618.         pos=pos->next;
  1619.         pos_num++;
  1620.       }
  1621.       if(pos_num>=offset+INTER_STRUCTURE)
  1622.         offset++;
  1623.     }
  1624.     break;
  1625.       case KEY_PPAGE:
  1626.     if(list_part!=NULL)
  1627.     {
  1628.       only_one_bootable(list_part,pos);
  1629.       for(i=0;(i<INTER_STRUCTURE) && (pos->prev!=NULL);i++)
  1630.       {
  1631.         pos=pos->prev;
  1632.         pos_num--;
  1633.         if(pos_num<offset)
  1634.           offset--;
  1635.       }
  1636.     }
  1637.     break;
  1638.       case KEY_NPAGE:
  1639.     if(list_part!=NULL)
  1640.     {
  1641.       only_one_bootable(list_part,pos);
  1642.       for(i=0;(i<INTER_STRUCTURE) && (pos->next!=NULL);i++)
  1643.       {
  1644.         pos=pos->next;
  1645.         pos_num++;
  1646.         if(pos_num>=offset+INTER_STRUCTURE)
  1647.           offset++;
  1648.       }
  1649.     }
  1650.     break;
  1651.       case KEY_RIGHT:
  1652.       case '+':
  1653.       case ' ':
  1654.     if(list_part!=NULL)
  1655.     {
  1656.       if(pos->part->status==STATUS_LOG)
  1657.         pos->part->status=STATUS_DELETED;
  1658.       else
  1659.         pos->part->status++;
  1660.       if(pos->part->status==STATUS_LOG && can_be_ext(disk_car,pos->part)==0)
  1661.         pos->part->status=STATUS_DELETED;
  1662.     }
  1663.     break;
  1664.       case KEY_LEFT:
  1665.       case '-':
  1666.     if(list_part!=NULL)
  1667.     {
  1668.       if(pos->part->status==STATUS_DELETED)
  1669.         pos->part->status=STATUS_LOG;
  1670.       else
  1671.         pos->part->status--;
  1672.       if(pos->part->status==STATUS_LOG && can_be_ext(disk_car,pos->part)==0)
  1673.         pos->part->status--;
  1674.     }
  1675.     break;
  1676.       case 'a':
  1677.       case 'A':
  1678.     {
  1679.       list_part=add_partition(disk_car,list_part, debug);
  1680.       rewrite=1;
  1681.       offset=0;
  1682.       pos_num=0;
  1683.       pos=list_part;
  1684.     }
  1685.     break;
  1686.       case 't':
  1687.       case 'T':
  1688.     if(list_part!=NULL)
  1689.     {
  1690.       rewrite=1;
  1691.       change_part_type(disk_car,pos->part);
  1692.     }
  1693.     break;
  1694.       case 'p':
  1695.       case 'P':
  1696.     if(list_part!=NULL)
  1697.     {
  1698.       WINDOW *window=newwin(0,0,0,0);    /* full screen */
  1699.       aff_copy(window);
  1700.       switch(pos->part->upart_type)
  1701.       {
  1702.         case UP_FAT12:
  1703.         case UP_FAT16:
  1704.         case UP_FAT32:
  1705.           dir_partition_fat(window,disk_car,pos->part,debug);
  1706.           break;
  1707.         case UP_EXT2:
  1708.         case UP_EXT3:
  1709.           dir_partition_ext2(window,disk_car,pos->part,debug);
  1710.           break;
  1711.         case UP_RFS:
  1712.         case UP_RFS2:
  1713.           dir_partition_reiser(window,disk_car,pos->part,debug);
  1714.           break;
  1715.         case UP_NTFS:
  1716.           dir_partition_ntfs(window,disk_car,pos->part,debug);
  1717.           break;
  1718.         default:
  1719.           break;
  1720.       }
  1721.       delwin(window);
  1722. #ifdef DJGPP
  1723.       wredrawln(stdscr,0,stdscr->_maxy);    /* redrawwin def is boggus in pdcur24 */
  1724. #else
  1725.       redrawwin(stdscr);    /* stdscr has been corrupted by window */
  1726. #endif
  1727.     }
  1728.     break;
  1729.       default:
  1730. /*    ecrit_rapport("ask_structure car=%x\n",car); */
  1731.     break;
  1732.     }
  1733.   } while(quit==0);
  1734.   return list_part;
  1735. }
  1736.  
  1737.